use axum::{Json, http::HeaderMap};
use serde_json::{Value, json};
use sea_orm::{ entity::*, query::*, DbErr, DatabaseConnection };

use com::{query, wx::{self, user_session::create_token, claims::get_id}, code, sea_orm::connect };
use model::wx_user::{ Entity, Column, ActiveModel };

//
pub async fn find(ident:&str, conn:&DatabaseConnection) -> Result<Option<Value>, Json<Value>>{
    let result = Entity::find()
    .select_only()
    .columns([Column::Id, Column::Name, Column::Nickname, Column::Phone, Column::Age, Column::Sex])
    .filter(Column::Ident.eq(ident))
    .into_json()
    .one(conn).await;
    match result {
        Ok(f) => Ok(f),
        Err(e) => Err(code::sys_(e.to_string()))
    }
}
// 存 appid, unionid, session_key，并生成 token 返回
pub async fn login(body:Value, appid:&str, secret:&str ) -> Result<Json<Value>, Json<Value>>{
    let code = query::str(&body, "code")?;    // js_code
    let mut rs: Value = wx::login::login(&code,appid,secret).await?;
    let ident = query::str(&rs, "ident")?;
    let conn = connect().await?;
    
    if let Some(mut f) = find(&ident, &conn).await? { // 用户存在
        rs["id"] = json!(query::i32(&f, "id")?);
        let token = create_token( rs )?;
        f["token"] = json!(token);
        return code::data(f)
    }else{  //  用户不存在时，存入数据据
        let model = ActiveModel{
            ident: Set(ident.to_owned()),
            from: Set("mf".into()),
            casc: Set(query::str_op(&rs, "casc")?),
            veri: Set(query::str(&rs, "veri")?),
            ..Default::default()
        };
        let result = model.insert(&conn).await;    // 插入内容
        match result {
            Ok(_f) => {
                let mut row = find(&ident, &conn).await?.unwrap();  // 读取内容
                rs["id"] = json!(query::i32(&row, "id")?);
                row["token"] = json!( create_token( rs )? );
                return code::data(row)
            },
            Err(e) => return code::sys(e.to_string())
        }
    }
}
// 检测登录态：校验服务器所保存的登录态 session_key 是否合法
// pub async fn check_login( Json(body):Json<Value> ) -> Result<Json<Value>, Json<Value>>{
//     let access_token = jn::body_str(&body, "access_token")?;
//     let uid = jn::body_str(&body, "uid")?; 
//     let signature = jn::body_str(&body, "signature")?; 
//     user::check_session_key(&access_token, &uid, &signature).await
// }
// 获取用户信息
pub async fn info(header:HeaderMap) -> Result<Json<Value>, Json<Value>>{
    let id = get_id(header)?;
    let conn = connect().await?;
    let result = Entity::find()
    .select_only()
    .columns([Column::Id, Column::Name, Column::Nickname, Column::Phone, Column::Age, Column::Sex ])
    .filter(Column::Id.eq(id))
    .into_json()
    .one(&conn).await;
    code::send_op_obj(result)
}
// 注册
pub async fn register(body:Value) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let id = query::i32(&body, "id")?;
    let nickname = query::str_op(&body, "nickname")?;
    let phone = query::str_op(&body, "phone")?;
    let transaction = conn.transaction::<_, Option<Value>, DbErr>(
        |txn|{
            Box::pin(async move {
                // 添加
                let model = ActiveModel{
                    id              : Set(id),
                    nickname        : Set( nickname ),
                    phone           : Set( phone ),
                    ..Default::default()
                };
                let _ = Update::one(model).exec(txn).await;
                // 查找
                let result = Entity::find_by_id(id)
                .select_only()
                .columns([Column::Id, Column::Name, Column::Nickname, Column::Phone, Column::Age, Column::Sex ])
                .into_json()
                .one(txn).await;
                match result {
                    Ok(f) => Ok(f),
                    Err(e) => Err(e)
                }
            })
        }
    ).await;
    code::send_op_obj(transaction)
    
}